package rpcserver

import (
	"go.etcd.io/etcd/clientv3"
	"google.golang.org/grpc"
	"grpc_etcd/register"
	"net"
	"fmt"
	"os"
	"os/signal"
	"syscall"
)

/**
对过程式的etcd client v3 + grpc 写法的抽象封装
 */
type RpcRegisterFunc func(*grpc.Server)

type RpcServer struct {
	registerFunc RpcRegisterFunc
	register *register.Register
}
type RpcServerConf struct {
	Key string
	ServerAddress string
	Endpoints []string
}
func NewRpcServer(conf *RpcServerConf,registerFunc RpcRegisterFunc)(*RpcServer,error){
	//create etcd client
	cli,err := clientv3.New(clientv3.Config{
		Endpoints:conf.Endpoints,
	})
	if err!=nil{
		return nil,err
	}
	return &RpcServer{
		register: register.New(cli,conf.Key,conf.ServerAddress),
		registerFunc:registerFunc,
	},nil
}
func (s *RpcServer)Run(opt ...grpc.ServerOption){
	//tcp监听
	listen,err := net.Listen("tcp",s.register.ServerAddress())
	if err!=nil{
		panic(err)
	}
	//注册 ip:port 到etcd
	s.register.RegisterServer()

	//creates a gRPC server
	server := grpc.NewServer(opt...)
	s.registerFunc(server) //回掉方法进行rpc方法注册

	s.deadNotify()

	fmt.Printf("学生服务 listen on  %s ...\n",s.register.ServerAddress())
	//开启服务监听
	if err = server.Serve(listen);err!=nil{
		fmt.Println("服务启动失败。")
		s.register.UnRegisterServer()
		panic(err)
	}
}
//系统死亡通知
func (s *RpcServer)deadNotify(){
	//监听系统信号
	ch := make(chan os.Signal,1)
	signal.Notify(ch,syscall.SIGTERM,syscall.SIGINT,syscall.SIGHUP,syscall.SIGKILL,syscall.SIGQUIT)
	go func() {
		fmt.Printf("系统异常退出。%v \n",<-ch)
		s.register.UnRegisterServer()
		os.Exit(1)
	}()
}